package com.dream.technology.service.impl;

import com.dream.technology.components.riskControl.SymbolAnalysis;
import com.dream.technology.components.riskControl.SymbolConstan;
import com.dream.technology.db.dao.RcFlowMapper;
import com.dream.technology.db.entity.*;
import com.dream.technology.db.entity.vo.ParentFlowVo;
import com.dream.technology.service.RcCustomerTagService;
import com.dream.technology.service.RcFlowItemService;
import com.dream.technology.service.RcFlowParentService;
import com.dream.technology.utils.RandomCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

//import com.dream.technology.zycashLog.Console;

@Service
public class RcFlowParentServiceImpl implements RcFlowParentService {

	@Autowired
    private RcFlowMapper rcFlowMapper;
	@Autowired
	private RcFlowItemService flowItemService;

	@Autowired
	private SymbolAnalysis symbolAnalysis;
    @Autowired
    private RcCustomerTagService tagService;


	@Override
    public int countByExample(RcFlowQuery example) {
        return rcFlowMapper.countByExample(example);
    }

    @Override
    @Transactional
    public int deleteByExample(RcFlowQuery example) {
        return rcFlowMapper.deleteByExample(example);
    }

    @Override
    @Transactional
    public int deleteByPrimaryKey(Long id) {
        return rcFlowMapper.deleteByPrimaryKey(id);
    }

    @Override
    @Transactional
    public int insert(RcFlow record) {
        return rcFlowMapper.insert(record);
    }

    @Override
    @Transactional
    public int insertSelective(RcFlow record) {
        return rcFlowMapper.insertSelective(record);
    }

    @Override
    public List<RcFlow> selectByExample(RcFlowQuery example) {
        return rcFlowMapper.selectByExample(example);
    }

    @Override
    @Transactional
    public RcFlow selectByPrimaryKey(Long id) {
        return rcFlowMapper.selectByPrimaryKey(id);
    }

    @Override
    @Transactional
    public int updateByExampleSelective(RcFlow record, RcFlowQuery example) {
        return rcFlowMapper.updateByExampleSelective(record, example);
    }

    @Override
    @Transactional
    public int updateByExample(RcFlow record, RcFlowQuery example) {
        return rcFlowMapper.updateByExample(record, example);
    }

    @Override
    @Transactional
    public int updateByPrimaryKeySelective(RcFlow record) {
        return rcFlowMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    @Transactional
    public int updateByPrimaryKey(RcFlow record) {
        return rcFlowMapper.updateByPrimaryKey(record);
    }

    /**
     * 创建总流程
     */
	@Override
	@Transactional
	public int add(String flowName, String flowDetail, Boolean enabled) {
		RcFlow record = new RcFlow();
		// 获取管理员
//        GenericRspDTO<OperationAdmin> userInfo = adminClient.getUserInfoByToken();
//        record.setAdminId(Long.valueOf(userInfo.getBody().getId()));
//        record.setCreator(userInfo.getBody().getUserName());
        record.setFlowCode(RandomCode.getRiskControlClaCode());
        // 封装总流程数据
    	record.setFlowName(flowName);
    	record.setFlowDetail(flowDetail);
    	record.setEnabled(enabled);
    	record.setStatus(false);
    	record.setFlowType(SymbolConstan.FLOW_TYPE_PARENT);
    	return insert(record);
	}

	/**
	 * 配置风控总流程
	 */
	@Override
	@Transactional
	public void updateByJsonStr(ParentFlowVo voFlow) {
        RcFlow rcFlow = voFlow.getFlow();
        List<RcFlowItem> rcFlowItems = voFlow.getRcFlowItems();
        String desc = checkFlow(voFlow);
        rcFlow.setFlowRuleDesc(desc);
        updateByPrimaryKeySelective(rcFlow);

        List<RcFlowItem> oldItems = flowItemService.selectByFlowId(rcFlow.getId());
        ArrayList<Long> itemIds = new ArrayList<>();

        rcFlowItems.forEach(item -> {
            if (item.getId() != null) {
                flowItemService.updateByPrimaryKeySelective(item);
                itemIds.add(item.getId());
            } else {
                item.setFlowId(rcFlow.getId());
                item.setEnabled(true);
                item.setStatus(false);
                flowItemService.insertSelective(item);
            }
        });
        List<RcFlowItem> deleteItems = oldItems.stream().filter(item -> !itemIds.contains(item.getId())).collect(Collectors.toList());
        deleteItems.forEach(item -> flowItemService.deleteByPrimaryKey(item.getId()));
	}

	/**
	 * 规则表达式生成文本描述
	 */
	@Override
    public String checkFlow(ParentFlowVo voFlow) {
        //总流程items
        List<RcFlowItem> rcFlowItems = voFlow.getRcFlowItems();
        //总流程
        RcFlow flow = voFlow.getFlow();
//        Map<String, String> aliasMap = new HashMap<>(rcFlowItems.size() << 1);
//        for (int i = 0; i < rcFlowItems.size(); i++) {
//            RcFlowItem item = rcFlowItems.get(i);
//            Long childItemId = item.getChildItemId();
//            String childAlias = item.getItemAlias();
//            // 重新映射 别名与描述
//            RcFlow rcFlow = rcFlowMapper.selectByPrimaryKey(childItemId);
//            aliasMap.put(childAlias, rcFlow.getFlowName());
//        }

        List<Long> flowIds = rcFlowItems.stream().map(RcFlowItem::getChildItemId).collect(Collectors.toList());
        RcFlowQuery query = new RcFlowQuery();
         query.createCriteria().andIdIn(flowIds);
        List<RcFlow> rcFlows = rcFlowMapper.selectByExample(query);
        Map<Long, String> collect = rcFlowItems.stream().collect(Collectors.toMap(RcFlowItem::getChildItemId, RcFlowItem::getItemAlias));
        Map<String, String> aliasMap = rcFlows.stream().collect(Collectors.toMap(f -> collect.get(f.getId()), f ->f.getFlowRuleDesc()+"<br/>"));
        return symbolAnalysis.getExp(flow.getFlowRule(), aliasMap);
    }

	/**
	 * 复制风控总流程
	 */
	@Override
    @Transactional
    public void copy(Long id, String flowName, String flowDetail, Boolean enabled) {
        RcFlow flow = rcFlowMapper.selectByPrimaryKey(id);
        flow.setFlowCode(RandomCode.getRiskControlClaCode());
        flow.setId(null);
        flow.setFlowName(flowName);
        flow.setFlowDetail(flowDetail);
        flow.setEnabled(enabled);
        flow.setCreateDate(new Date());
        insertSelective(flow);
        flowItemService.copy(id, flow.getId());
    }


    /**
     *  获取某个总流程下的所有用户标签
     * @param flowId
     * @return
     */
    @Override
    public List<RcCustomerTag>  getVoTag(Long flowId){
        RcFlowItemQuery query = new RcFlowItemQuery();
        query.createCriteria().andFlowIdEqualTo(flowId).andChildItemTypeEqualTo(Integer.valueOf( SymbolConstan.FLOW_ITEM_TYPE_SON_FLOW));
        List<RcFlowItem> rcFlowItems = flowItemService.selectByExample(query);
        List<Long> childFlowIds = new ArrayList<>();
        //拿到说有的子流程id
        rcFlowItems.forEach(flow ->childFlowIds.add(flow.getChildItemId()));

        RcFlowItemQuery queryTag = new RcFlowItemQuery();
        queryTag.createCriteria().andChildItemTypeEqualTo(Integer.valueOf(SymbolConstan.FLOW_ITEM_TYPE_TAG)).andFlowIdIn(childFlowIds);
        //总流程下所有用户标签
        List<RcFlowItem> rcFlowTagItems = flowItemService.selectByExample(queryTag);

        List<Long> tagIds = new ArrayList<>();
        rcFlowTagItems.forEach(tag ->tagIds.add(tag.getChildItemId()));

        RcCustomerTagQuery tagQuery = new RcCustomerTagQuery();
        tagQuery.createCriteria().andIdIn(tagIds);
        List<RcCustomerTag> customerTags = tagService.selectByExample(tagQuery);


        return  customerTags;
    }

    /**
     * 根据子流程 ，用户标签id查找流程
     *
     * @param items
     * @param tagId
     * @return
     */
    @Override
    public RcFlow getChildFlow(List<RcFlowItem> items, Long tagId) {
        List<Long> flowIds = new ArrayList<>();
        items.forEach(flow -> flowIds.add(flow.getChildItemId()));
        RcFlowItemQuery query = new RcFlowItemQuery();
        query.createCriteria().andFlowIdIn(flowIds)
                .andChildItemTypeEqualTo(Integer.valueOf( SymbolConstan.FLOW_ITEM_TYPE_TAG))
                .andChildItemIdEqualTo(tagId);

        List<RcFlowItem> rcFlowItems = flowItemService.selectByExample(query);
        RcFlowItem item = rcFlowItems.get(0);
        RcFlow flow = rcFlowMapper.selectByPrimaryKey(item.getFlowId());
        //Console.info("命中的子流程为 == {}",flow.getFlowName());
        return  flow;
    }

}
